﻿using RM.BasicLibrary.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RM.BasicLibrary
{
    /// <summary>
    /// 集合扩展方法
    /// </summary>
    public static partial class Extension
    {
        public static bool IsObjectGenericIEnumerable<T>(this T o)
        {
            return o is System.Collections.IEnumerable && (o.GetType().IsGenericType || o is Array);
        }
        /// <summary>
        /// 判断指定的类型 <paramref name="type"/> 是否是指定泛型类型的子类型，或实现了指定泛型接口。
        /// </summary>
        /// <param name="type">需要测试的类型。</param>
        /// <param name="generic">泛型接口类型，传入 typeof(IXxx&lt;&gt;)</param>
        /// <returns>如果是泛型接口的子类型，则返回 true，否则返回 false。</returns>
        public static bool HasImplementedRawGeneric(this Type type, Type generic)
        {
            if (type == null) throw new ArgumentNullException(nameof(type));
            if (generic == null) throw new ArgumentNullException(nameof(generic));

            // 测试接口。
            var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
            if (isTheRawGenericType) return true;

            // 测试类型。
            while (type != null && type != typeof(object))
            {
                isTheRawGenericType = IsTheRawGenericType(type);
                if (isTheRawGenericType) return true;
                type = type.BaseType;
            }
            // 没有找到任何匹配的接口或类型。
            return false;
            // 测试某个类型是否是指定的原始接口。
            bool IsTheRawGenericType(Type test)
                => generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test);
        }
        /// <summary>
        /// Joins the strings into one single string interspersing the elements with the separator (a-la
        /// System.String.Join()).
        /// </summary>
        /// <param name="elements">The elements.</param>
        /// <param name="separator">The separator.</param>
        /// <returns>The joined string.</returns>
        public static string JoinWith(this IEnumerable<string> elements, string separator)
        {
            if (elements == null) throw new ArgumentNullException(nameof(elements));
            if (separator == null) throw new ArgumentNullException(nameof(separator));

            return string.Join(separator, elements.ToArray());
        }

        /// <summary>
        /// Appends the item to the specified sequence.
        /// </summary>
        /// <typeparam name="T">The type of element in the sequence.</typeparam>
        /// <param name="sequence">The sequence.</param>
        /// <param name="trailingItem">The trailing item.</param>
        /// <returns>The sequence with an item appended to the end.</returns>
        public static IEnumerable<T> AppendItem<T>(this IEnumerable<T> sequence, T trailingItem)
        {
            if (sequence == null) throw new ArgumentNullException(nameof(sequence));

            foreach (var t in sequence)
                yield return t;

            yield return trailingItem;
        }

        /// <summary>
        /// Prepends the item to the specified sequence.
        /// </summary>
        /// <typeparam name="T">The type of element in the sequence.</typeparam>
        /// <param name="sequence">The sequence.</param>
        /// <param name="leadingItem">The leading item.</param>
        /// <returns>The sequence with an item prepended.</returns>
        public static IEnumerable<T> Prepend<T>(this IEnumerable<T> sequence, T leadingItem)
        {
            if (sequence == null) throw new ArgumentNullException(nameof(sequence));

            yield return leadingItem;

            foreach (var t in sequence)
                yield return t;
        }

        public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
        {
            foreach (var item in items)
                collection.Add(item);
        }
        /// <summary>
        /// 获取list的分页数据
        /// </summary>
        /// <param name="obj">list对象</param>
        /// <param name="pagination">分页参数</param>
        /// <returns></returns>
        public static List<T> FindPage<T>(this List<T> obj, Pagination pagination) where T : class
        {
            pagination.Records = obj.Count;
            int index = (pagination.Page - 1) * pagination.Rows;
            if (index >= obj.Count)
            {
                return new List<T>();
            }
            int end = index + pagination.Rows;
            int count = end > obj.Count ? obj.Count - index : pagination.Rows;
            List<T> list = obj.GetRange(index, count);
            return list;
        }
    }
}

